package com.qf.index;

import cn.hutool.core.collection.ConcurrentHashSet;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.db.Db;
import cn.hutool.db.Entity;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;

import java.io.IOException;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Pattern;

public class TestSearch {
    /**
     * 与福磊比对ES的逻辑组合检索。
     * 贾新志 2024.12.31
     */
    public static void main(String[] args) throws SQLException, IOException {
        TestAdSearch();


// main
    }

    public static void TestAdSearch() {
        Set<En.PmIdYearInfo> pmIdYearInfoSet = new ConcurrentHashSet<>();
        String c1Au = "[{\"country\":\"中国\",\"fuDanSet\":[],\"sort\":1,\"stdUnit\":[],\"unitSet\":[\"peoples liberat army general hospital\"],\"deptSet\":[],\"stemSet\":[],\"authList\":[\"Chen, Baoguo\",\"Li, Huichao\"],\"eduSet\":[],\"info\":\"Peoples Liberat Army Gen Hosp, Affiliate Hosp 1, Burs & Plast Surg, Beijing, Peoples R China\",\"full\":\"Peoples Liberat Army General Hospital, Affiliate Hospital 1, Burs & Plast Surgeons, Beijing, People's Republic of China\"},{\"country\":\"中国\",\"fuDanSet\":[],\"sort\":2,\"stdUnit\":[],\"unitSet\":[\"former fourth military medical hospital\"],\"deptSet\":[],\"stemSet\":[],\"authList\":[\"Xia, Wei\"],\"eduSet\":[],\"info\":\"Former Fourth Mil Med Hosp, Plast & Reconstruct Surg, Xian, Shaanxi, Peoples R China\",\"full\":\"Former Fourth Military Medical Hospital, Plast & Reconstruct Surgeons, Xian, Shaanxi, People's Republic of China\"}]";
        String rpAu = "[{\"country\":\"中国\",\"fuDanSet\":[],\"sort\":1,\"stdUnit\":[],\"unitSet\":[\"former fourth military medical hospital\"],\"deptSet\":[],\"stemSet\":[],\"authList\":[\"Xia, Wei\"],\"eduSet\":[],\"info\":\"Former Fourth Mil Med Hosp, Plast & Reconstruct Surg, Xian, Shaanxi, Peoples R China\",\"full\":\"Former Fourth Military Medical Hospital, Plast & Reconstruct Surgeons, Xian, Shaanxi, People's Republic of China\"}]";
        List<En.C1Auth> c1List = (c1Au.contains("sort")) ? JSONObject.parseArray(c1Au, En.C1Auth.class) : new ArrayList<>();
        List<En.C1Auth> rpList = (rpAu.contains("sort")) ? JSONObject.parseArray(rpAu, En.C1Auth.class) : new ArrayList<>();
        En.PmIdYearInfo pmIdYearInfos = new En.PmIdYearInfo();
        List<String> c1s = new ArrayList<>();
        for (En.C1Auth c1Auth : c1List) {
            c1s.add(c1Auth.getInfo());
        }
        List<String> rps = new ArrayList<>();
        for (En.C1Auth c1Auth : rpList) {
            rps.add(c1Auth.getInfo());
        }
        pmIdYearInfos.setYear(2019);
        pmIdYearInfos.setPmId(31475447);
        pmIdYearInfos.setC1List(c1s);
        pmIdYearInfos.setRpList(rps);
        pmIdYearInfoSet.add(pmIdYearInfos);

        En.SearchSet searchSet = new En.SearchSet();
        searchSet.setC1(1);
        searchSet.setRp(0);
        searchSet.setAndOrOr(1);
        searchSet.getYearList().add(2019);
        searchSet.getYearList().add(2020);
        searchSet.getYearList().add(2021);
        searchSet.getYearList().add(2022);
        searchSet.getYearList().add(2023);
        searchSet.getYearList().add(2024);
        searchSet.getYearList().add(2025);
        Set<Integer> yearSet = new HashSet<>(searchSet.getYearList());

        Integer order = 1;
        int c1 = 0;
        int rp = 0;
        int andOrOr = 1;
        String kw = "AD=((Beijing Univ Chinese Med OR Beijing Univ Tradit Chinese Med OR Beijing) SAME (Dongzhimen Hosp OR Dong Zhi Men Hosp OR Affiliated Hosp 1))";

        Map<String, Boolean> infoKwAndBoolMap = new HashMap<>();
        pmIdYearInfoSet.forEach(pmIdYearInfo -> {
            int year = pmIdYearInfo.getYear();
            int pmId = pmIdYearInfo.getPmId();
            System.out.println(pmIdYearInfo);
            if (yearSet.contains(year)) {
                List<String> c1SumList = TestSearch.getSum(pmIdYearInfo.getC1List(), kw, c1, infoKwAndBoolMap);
                List<String> rpSumList = TestSearch.getSum(pmIdYearInfo.getRpList(), kw, rp, infoKwAndBoolMap);
                boolean result = false;
                if (andOrOr == 1) {
                    if (!c1SumList.isEmpty() || !rpSumList.isEmpty()) {
                        result = true;
                    }
                } else {
                    if (!c1SumList.isEmpty() && !rpSumList.isEmpty()) {
                        result = true;
                    }
                }
                if (result) {
                    System.out.println("c1SumList:" + c1SumList);
                    System.out.println("rpSumList:" + rpSumList);
                }
            }
        });
    }

    public static void doRun() throws SQLException {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println(format.format(new Date()) + " 程序开始了~~~");
        String newDataName = "scholar_25_02.";
        String summaryTable = newDataName + "unified_search_summary_0120";
        String orderPmIdAdKwTable = newDataName + "order_pmid_ad_kw";
        String first5Table = newDataName + "order_name_search_first_5_pmid_list_sum";
        String pmArticleTable = newDataName + "spider_pubmed_vip_extend";
        String pmIdYearC1sRpsTable = newDataName + "pmid_year_c1s_rps";

        String limit = "";
//        String limit = " limit 1";

        Db.use().execute("truncate table " + pmIdYearC1sRpsTable);
        Set<En.PmIdYearInfo> pmIdYearInfoSet = getPmIdYearInfoSet(summaryTable, "id", "pmId`,`year`,`c1_au`,`rp_au", limit, pmIdYearC1sRpsTable);
        Set<En.PmIdYearInfo> pmIdYearInfos = readPmIdYearInfoSet(pmIdYearC1sRpsTable, "id", "info");

        En.SearchSet searchSet = new En.SearchSet();
        searchSet.setC1(1);
        searchSet.setRp(0);
        searchSet.setAndOrOr(1);
        searchSet.getYearList().add(2019);
        searchSet.getYearList().add(2020);
        searchSet.getYearList().add(2021);
        searchSet.getYearList().add(2022);
        searchSet.getYearList().add(2023);
        searchSet.getYearList().add(2024);
        searchSet.getYearList().add(2025);
        Set<Integer> yearSet = new HashSet<>(searchSet.getYearList());

        // 检索测试，分别以001，111，000，110，101五种进行测试，测试时并没有使用检索设置（searchSet），而是直接给的值。
        // C1:只要第一作者，为1，默认为1，全部都要为0。RP:只要第一通讯作者，为1，默认为1，全部都要为0。andOrOr：作者和通讯之间的关系，默认为OR，为1，意思是作者是可以，通讯是也可以，两个都要（即两个都要满足为0）。
        Map<Integer, String> orderAndInfoMap = getOrderAndInfoMap();
        Db.use().execute("truncate table " + orderPmIdAdKwTable);
        for (Map.Entry<Integer, String> entry : orderAndInfoMap.entrySet()) {
            Map<String, Boolean> infoKwAndBoolMap = new ConcurrentHashMap<>();
            Integer order = entry.getKey();
            String kw = entry.getValue();
            doSearch(kw, pmIdYearInfos, yearSet, orderPmIdAdKwTable, order, 0, 0, 1, infoKwAndBoolMap);
            doSearch(kw, pmIdYearInfos, yearSet, orderPmIdAdKwTable, order, 1, 1, 1, infoKwAndBoolMap);
            doSearch(kw, pmIdYearInfos, yearSet, orderPmIdAdKwTable, order, 0, 0, 0, infoKwAndBoolMap);
            doSearch(kw, pmIdYearInfos, yearSet, orderPmIdAdKwTable, order, 1, 1, 0, infoKwAndBoolMap);
            doSearch(kw, pmIdYearInfos, yearSet, orderPmIdAdKwTable, order, 1, 0, 1, infoKwAndBoolMap);
            System.out.println(format.format(new Date()) + " order: " + order + " pmIdYearInfos.size():" + pmIdYearInfos.size() + " infoKwAndBoolMap.size():" + infoKwAndBoolMap.size() + Utils.printMemoryStr());
        }

        Map<Integer, byte[]> pmIdAndAdListMap = ReadAd.getPmIdAndAdListMap(pmArticleTable, "id", "pmid`,`author_extend", limit);
        System.out.println("pmIdAndAdListMap.size(): " + pmIdAndAdListMap.size());
        ReadAd.updateOrderPmIdAdKwTable(orderPmIdAdKwTable, "id", "pmid`,`ut_c1", pmIdAndAdListMap);

        Db.use().execute("truncate table " + first5Table);
        insertFirst5Table(orderPmIdAdKwTable, "id", "pm_ad`,`order`,`pmid", first5Table);
    }

    public static void insertFirst5Table(String orderPmIdAdKwTable, String autoId, String field, String first5Table) throws SQLException {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        int onePageNum = 1000;
        Map<Integer, Map<String, Integer>> orderWordSumMap = new ConcurrentHashMap<>();
        Map<Integer, Set<Integer>> orderPmIdSetMap = new ConcurrentHashMap<>();
        int tableMax = Db.use().queryNumber("select max(" + autoId + ") from " + orderPmIdAdKwTable).intValue();
        if (tableMax > 0) {
            Collection<Integer> tableList = new ArrayList<>();
            NumberUtil.appendRange(0, tableMax + onePageNum, onePageNum, tableList);
            for (Integer startId : tableList) {
                List<Entity> tableData = Db.use().query("select `" + autoId + "`,`" + field + "` from " + orderPmIdAdKwTable + " where " + autoId + " between " + startId + " and " + (startId + onePageNum - 1));
                System.out.println("\033[31;1m" + format.format(new Date()) + " 读表现在开始：" + startId + " 表名：" + orderPmIdAdKwTable + Utils.printMemoryStr() + "\033[0m");
                for (Entity entry : tableData) {
                    String pmAd = Utils.getStrField(entry, "pm_ad");
                    int order = Utils.getIntField(entry, "order");
                    int pmId = Utils.getIntField(entry, "pmid");
                    if (order > 0 && pmId > 0) {
                        if (pmAd.length() > 8) {
                            String[] split = pmAd.split(", ");
                            for (String s : split) {
                                s = s.trim().replace("People's Republic of China", "China").replace("P.R. China", "China").replace("PR China", "China");
                                if (s.contains(" ") && !Pattern.compile("[0-9]{4,6}").matcher(s).find() && !s.contains("Department") && !s.contains("Key Laboratory") && !s.contains(" Road")) {
                                    Utils.putIntStrIntSum(order, s, orderWordSumMap);
                                }
                            }
                        }
                        Utils.putIntSetIntMap(orderPmIdSetMap, order, pmId);
                    }
                }
            }
        }
        List<String> list = FileUtil.readLines("C:\\临时文件\\2025_02\\temp_order_name_search.txt", "utf-8");
        for (String s : list) {
            String[] split = s.split("_");
            if (split.length == 3 && NumberUtil.isInteger(split[0])) {
                int order = Integer.parseInt(split[0]);
                Map<String, Integer> first5Map = new HashMap<>();
                if (orderWordSumMap.containsKey(order)) {
                    first5Map = Utils.mapSortValueIntLen(orderWordSumMap.get(order), 10);
                }
                Set<Integer> pmIdSet = orderPmIdSetMap.containsKey(order) ? orderPmIdSetMap.get(order) : new HashSet<>();
                try {
                    Db.use().insert(Entity.create(first5Table).set("order", order).set("name", split[1]).set("search", split[2]).set("sum", pmIdSet.size())
                            .set("firsr_5_word", JSONUtil.toJsonStr(first5Map)).set("pmid_list", JSONUtil.toJsonStr(pmIdSet)));
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static List<String> getSum(List<String> c1List, String kw, int c1, Map<String, Boolean> infoKwAndBoolMap) {
        List<String> rList = new ArrayList<>();
        for (String info : c1List) {
            String infoKw = info.toUpperCase().trim() + "_" + kw;
            boolean bool = false;
            if (infoKwAndBoolMap.containsKey(infoKw)) {
                bool = infoKwAndBoolMap.get(infoKw);
            } else {
                bool = AdSearch.doCheck(info, AdSearch.checkGrammar(kw));
                System.out.println("info:" + info + " kw:" + AdSearch.checkGrammar(kw) + " bool:" + bool);
                infoKwAndBoolMap.put(infoKw, bool);
            }
            if (bool) {
                rList.add(info);
            }
            if (c1 == 1) {
                return rList;
            }
        }
        return rList;
    }

    public static void doSearch(String kw, Set<En.PmIdYearInfo> pmIdYearInfoSet, Set<Integer> yearSet, String orderPmIdAdKwTable, int order, int c1, int rp, int andOrOr, Map<String, Boolean> infoKwAndBoolMap) {
        pmIdYearInfoSet.parallelStream().forEach(pmIdYearInfo -> {
            int year = pmIdYearInfo.getYear();
            int pmId = pmIdYearInfo.getPmId();
            if (yearSet.contains(year)) {
                List<String> c1SumList = getSum(pmIdYearInfo.getC1List(), kw, c1, infoKwAndBoolMap);
                List<String> rpSumList = getSum(pmIdYearInfo.getRpList(), kw, rp, infoKwAndBoolMap);
                boolean result = false;
                if (andOrOr == 1) {
                    if (!c1SumList.isEmpty() || !rpSumList.isEmpty()) {
                        result = true;
                    }
                } else {
                    if (!c1SumList.isEmpty() && !rpSumList.isEmpty()) {
                        result = true;
                    }
                }
                if (result) {
                    try {
                        Db.use().insert(Entity.create(orderPmIdAdKwTable).set("order", order).set("ut_c1", JSONUtil.toJsonStr(c1SumList)).set("ut_rp", JSONUtil.toJsonStr(rpSumList)).set("pmid", pmId).set("kw", kw).set("type", (Integer.toString(c1) + rp + andOrOr)));
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
    }

    public static Map<Integer, String> getOrderAndInfoMap() {
        String filePath = "C:\\临时文件\\2025_02\\temp_hosp.txt";
        Map<Integer, String> orderAndInfoMap = new HashMap<>();
        List<String> pathList = FileUtil.readLines(filePath, "utf-8");
        for (String s : pathList) {
            String[] split = s.split("_");
            if (split.length == 2 && NumberUtil.isInteger(split[0]) && split[1].contains("=")) {
                orderAndInfoMap.put(Integer.parseInt(split[0]), split[1]);
            }
        }
        return orderAndInfoMap;
    }

    public static Set<En.PmIdYearInfo> readPmIdYearInfoSet(String pmIdYearC1sRpsTable, String autoId, String field) throws SQLException {
        int onePageNum = 1000;
        List<Entity> tableNum = Db.use().query("select count(1) as count from " + pmIdYearC1sRpsTable);
        Set<En.PmIdYearInfo> pmIdYearInfoSet = new ConcurrentHashSet<>();
        if (tableNum.get(0).getInt("count") > 0) {
            int tableMax = Db.use().queryNumber("select max(" + autoId + ") from " + pmIdYearC1sRpsTable).intValue();
            Collection<Integer> tableList = new ArrayList<>();
            NumberUtil.appendRange(0, tableMax + onePageNum, onePageNum, tableList);
            for (Integer startId : tableList) {
                List<Entity> tableData = Db.use().query("select `" + autoId + "`,`" + field + "` from " + pmIdYearC1sRpsTable + " where " + autoId + " between " + startId + " and " + (startId + onePageNum - 1));
                for (Entity entry : tableData) {
                    String info = entry.getStr("info");
                    if (null != info && info.contains("c1List")) {
                        En.PmIdYearInfo pmIdYearInfo = JSONObject.parseObject(info, En.PmIdYearInfo.class);
                        pmIdYearInfoSet.add(pmIdYearInfo);
                    }
                }
            }
        }
        return pmIdYearInfoSet;
    }

    public static Set<En.PmIdYearInfo> getPmIdYearInfoSet(String summaryOldTable, String autoId, String field, String limit, String pmIdYearC1sRpsTable) throws SQLException {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        int onePageNum = 1000;
        Set<En.PmIdYearInfo> pmIdYearInfoSet = new ConcurrentHashSet<>();
        List<Entity> tableNum = Db.use().query("select count(1) as count from " + summaryOldTable);
        if (tableNum.get(0).getInt("count") > 0) {
            int tableMax = Db.use().queryNumber("select max(" + autoId + ") from " + summaryOldTable).intValue();
            Collection<Integer> tableList = new ArrayList<>();
            NumberUtil.appendRange(0, tableMax + onePageNum, onePageNum, tableList);
            tableList.parallelStream().forEach(startId -> {
                try {
                    List<Entity> tableData = Db.use().query("select `" + autoId + "`,`" + field + "` from " + summaryOldTable + " where " + autoId + " between " + startId + " and " + (startId + onePageNum - 1) + limit);
                    System.out.println("\033[31;1m" + format.format(new Date()) + " 读表现在开始：" + startId + " 表名：" + summaryOldTable + Utils.printMemoryStr() + "\033[0m");
                    for (Entity entry : tableData) {
                        Integer pmId = entry.getInt("pmId");
                        Integer year = entry.getInt("year");
                        if (null != year && year > 2018 && null != pmId && pmId > 0) {
                            String c1Au = Utils.getStrField(entry, "c1_au");
                            String rpAu = Utils.getStrField(entry, "rp_au");
                            List<En.C1Auth> c1List = (c1Au.contains("sort")) ? JSONObject.parseArray(c1Au, En.C1Auth.class) : new ArrayList<>();
                            List<En.C1Auth> rpList = (rpAu.contains("sort")) ? JSONObject.parseArray(rpAu, En.C1Auth.class) : new ArrayList<>();
                            En.PmIdYearInfo pmIdYearInfo = new En.PmIdYearInfo();
                            List<String> c1s = new ArrayList<>();
                            for (En.C1Auth c1Auth : c1List) {
                                c1s.add(c1Auth.getInfo());
                            }
                            List<String> rps = new ArrayList<>();
                            for (En.C1Auth c1Auth : rpList) {
                                rps.add(c1Auth.getInfo());
                            }
                            pmIdYearInfo.setYear(year);
                            pmIdYearInfo.setPmId(pmId);
                            pmIdYearInfo.setC1List(c1s);
                            pmIdYearInfo.setRpList(rps);
                            if (!pmIdYearInfoSet.contains(pmIdYearInfo)) {
                                try {
                                    Db.use().insert(Entity.create(pmIdYearC1sRpsTable).set("info", JSONUtil.toJsonStr(pmIdYearInfo)));
                                    pmIdYearInfoSet.add(pmIdYearInfo);
                                } catch (SQLException e) {
                                    e.printStackTrace();
                                }
                            }
                        }
                    }
                } catch (SQLException e) {
//                    throw new RuntimeException(e);
                }
            });
        }
        return pmIdYearInfoSet;
    }


}
